Binary Tree Traversal
Breadth First Search (BFS)
BFS is also known a Level-order Traversal as it moves through each level of the tree, before moving to the next. This is typically best to code with a queue, in which each node is considered, and if it has left of right nodes, then those are added to the queue.
def bfs_recursive1(root):
node = root
queue = deque() # Could also use a list here
result = []
queue.append(node)
while len(queue) > 0:
node = queue.popleft()
result.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
#out: [1,2,3,4,5,6,7,...]
def bfs_recursive2(root):
node = root
queue = deque() # Could also use a list here
next_queue = deque()
result = []
queue.append(node)
while len(queue) > 0:
result.append([node.val for node in queue])
for node in queue:
if node.left:
next_queue.append(node.left)
if node.right:
next_queue.append(node.right)
queue = next_queue
next_queue = []
return results
#out: [[1], [2,3], [4,5,6,7],...]
def bfs_recursive1(root):
node = root
queue = deque() # Could also use a list here
result = []
queue.append(node)
while len(queue) > 0:
node = queue.popleft()
result.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
#out: [1,2,3,4,5,6,7,...]
def bfs_recursive2(root):
node = root
queue = deque() # Could also use a list here
next_queue = deque()
result = []
queue.append(node)
while len(queue) > 0:
result.append([node.val for node in queue])
for node in queue:
if node.left:
next_queue.append(node.left)
if node.right:
next_queue.append(node.right)
queue = next_queue
next_queue = []
return results
#out: [[1], [2,3], [4,5,6,7],...]
Depth First Search (DFS)
DFS searches all the way down a branch before moving to the next branch. There are three ways to search with DFS, which depend mainly on when the item is added to the results
Pre-order Traversal
Pre-order traversal adds elements to its search output before checking to see whether there are left or right nodes.
def dfs_preorder_recursive1(root):
results = []
def traverse(node):
results.append(node)
if node.left:
traverse(node.left)
if node.right:
traverse(node.right)
traverse(root)
return results
def dfs_preorder_recursive2(root):
results = []
def traverse(node):
if node:
results.append(node.val)
traverse(node.left)
traverse(node.right)
traverse(root)
return results
def dfs_preorder_iterative1(root):
node = root
stack = deque()
results = []
stack.append(node)
while len(stack) > 0:
if node is not None:
results.append(node.val)
stack.append(node)
node = node.left
else:
node = stack.pop()
node = node.right
return results
def dfs_preorder_iterative2(root):
node = root
stack = deque()
results = []
stack.append(node)
while len(stack) > 0:
node = stack.pop()
results.append(node.val)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return results
def dfs_preorder_recursive1(root):
results = []
def traverse(node):
results.append(node)
if node.left:
traverse(node.left)
if node.right:
traverse(node.right)
traverse(root)
return results
def dfs_preorder_recursive2(root):
results = []
def traverse(node):
if node:
results.append(node.val)
traverse(node.left)
traverse(node.right)
traverse(root)
return results
def dfs_preorder_iterative1(root):
node = root
stack = deque()
results = []
stack.append(node)
while len(stack) > 0:
if node is not None:
results.append(node.val)
stack.append(node)
node = node.left
else:
node = stack.pop()
node = node.right
return results
def dfs_preorder_iterative2(root):
node = root
stack = deque()
results = []
stack.append(node)
while len(stack) > 0:
node = stack.pop()
results.append(node.val)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return results
In-order Traversal
In-order traversal adds elements to its search output after checking if it has a left node but before checking for a right node.
def dfs_inorder_recursive(root):
results = []
def traverse(node):
if node.left:
traverse(node.left)
results.append(node)
if node.right:
traverse(node.right)
traverse(root)
return results
def dfs_inorder_recursive2(root):
results = []
def traverse(node):
if node:
traverse(node.left)
results.append(node.val)
traverse(node.right)
traverse(root)
return results
def dfs_inorder_iterative1(root):
node = root
stack = deque()
results = []
stack.append(node)
while len(stack) > 0:
if node is not None:
stack.append(node)
node = node.left
else:
node = stack.pop()
results.append(node.val)
node = node.right
return results[:len(results)-1]
def dfs_inorder_recursive(root):
results = []
def traverse(node):
if node.left:
traverse(node.left)
results.append(node)
if node.right:
traverse(node.right)
traverse(root)
return results
def dfs_inorder_recursive2(root):
results = []
def traverse(node):
if node:
traverse(node.left)
results.append(node.val)
traverse(node.right)
traverse(root)
return results
def dfs_inorder_iterative1(root):
node = root
stack = deque()
results = []
stack.append(node)
while len(stack) > 0:
if node is not None:
stack.append(node)
node = node.left
else:
node = stack.pop()
results.append(node.val)
node = node.right
return results[:len(results)-1]
Post-order Traversal
Post-order traversal adds elements to its search output after checking for the existence of either its left and right nodes.
def dfs_inorder_recursive(root):
results = []
def traverse(node):
if node.left:
traverse(node.left)
if node.right:
traverse(node.right)
results.append(node)
traverse(root)
return results
def dfs_inorder_recursive2(root):
results = []
def traverse(node):
if node:
traverse(node.left)
traverse(node.right)
results.append(node.val)
traverse(root)
return results
def dfs_postorder_iterative1(root):
node = root
stack = deque()
results = []
stack.append(node)
while len(stack) > 0:
node = stack.pop()
results.append(node.val)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
out = []
while results:
out.append(results.pop())
return out
def dfs_inorder_recursive(root):
results = []
def traverse(node):
if node.left:
traverse(node.left)
if node.right:
traverse(node.right)
results.append(node)
traverse(root)
return results
def dfs_inorder_recursive2(root):
results = []
def traverse(node):
if node:
traverse(node.left)
traverse(node.right)
results.append(node.val)
traverse(root)
return results
def dfs_postorder_iterative1(root):
node = root
stack = deque()
results = []
stack.append(node)
while len(stack) > 0:
node = stack.pop()
results.append(node.val)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
out = []
while results:
out.append(results.pop())
return out